/**
 * 版权所有(C)，上海海鼎信息工程股份有限公司，2007，所有权利保留。
 * 
 * 项目名：	rumba
 * 文件名：	PromptProviderFactory.java
 * 模块说明：	
 * 修改历史：
 * Nov 5, 2007 - lxm - 创建。
 */
package com.hd123.rumba.prompt.provider;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import net.sf.hibernate.HibernateException;

import com.hd123.rumba.cartridge.ICartFunctionView;
import com.hd123.rumba.cartridge.biz.BCartFunctionView;
import com.hd123.rumba.domain.IDomain;
import com.hd123.rumba.domain.IDomainMgr;
import com.hd123.rumba.exception.BusinessException;
import com.hd123.rumba.log.RumbaLogger;
import com.hd123.rumba.runtime.NamingMgr;

/**
 * rumba系统提供者工厂类
 * <p>
 * 
 * Singleton。
 * 
 * @author lxm
 * 
 */
public class PromptProviderFactory {

  private static PromptProviderFactory instance = null;
  private static RumbaLogger logger = RumbaLogger.getLogger(PromptProviderFactory.class);

  private Map<String, IPromptProvider> registry = null;

  private PromptProviderFactory() {
    super();
    this.registry = new HashMap<String, IPromptProvider>();
  }

  public static PromptProviderFactory getInstance() {
    if (instance == null)
      instance = new PromptProviderFactory();
    return instance;
  }

  /**
   * 注册一个提醒提供者。
   * <p>
   * 
   * 一般被放在系统初始化时被调用。
   * 
   * @param providerClass
   *          指定提醒提供者类。要求必须实现接口{@link IPromptProvider}
   * @throws BusinessException
   */
  public void registerProvider(Class providerClass) throws BusinessException {
    if (providerClass == null)
      throw new BusinessException("参数providerClass不可为null。");

    boolean valid = false;
    for (Class clazz : providerClass.getInterfaces())
      if (clazz.getName().equals(IPromptProvider.class.getName())) {
        valid = true;
        break;
      }
    if (!valid)
      throw new BusinessException("参数providerClass指定的类必须支持接口" + IPromptProvider.class.getName()
          + "。");

    if (!this.registry.containsKey(providerClass.getName())) {
      IPromptProvider provider = null;
      try {
        provider = (IPromptProvider) Class.forName(providerClass.getName()).newInstance();
      } catch (Exception e) {
        logger.error("无法创建指定的提醒提供者(IPromptProvider):" + providerClass.getName(), e);
      }
      this.registry.put(providerClass.getName(), provider);
    }
  }

  /**
   * 取得提醒提供者对象实例。
   * 
   * @param className
   *          指定提供者类名。
   * @return 提醒提供者对象实例。
   * @throws BusinessException
   */
  public IPromptProvider getProvider(String className) throws BusinessException {
    return this.registry.get(className);
  }

  /**
   * 取得指定域所有可用的提醒提供者对象。
   * 
   * @param domain
   *          指定域。
   * @return
   * @throws BusinessException
   * @throws HibernateException
   */
  public List<IPromptProvider> getProvidersByDomain(IDomain domain) throws BusinessException,
      HibernateException {
    if (domain == null)
      throw new BusinessException("参数domain不可为null。");

    IDomainMgr dmMgr = (IDomainMgr) NamingMgr.getInstance().lookupMgr(IDomainMgr.class);
    List<ICartFunctionView> cfvs = dmMgr.getCFVsByDomain(domain);

    List<IPromptProvider> ret = new ArrayList<IPromptProvider>();
    for (IPromptProvider provider : this.registry.values()) {
      BCartFunctionView cfv = provider.getCFV();
      if (cfv != null) {
        boolean contain = false;
        for (ICartFunctionView cfv2 : cfvs)
          if (cfv2.getUuid().equals(cfv.getUuid())) {
            contain = true;
            break;
          }
        if (!contain)
          continue;
      }
      ret.add(provider);
    }

    return ret;
  }

}
